package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.web.feign.PaymentFeignService;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.bo.MerchantBO;
import com.tiancheng.trade.settlement.bo.MerchantPaymentChannelBO;
import com.tiancheng.trade.settlement.bo.ProductBO;
import com.tiancheng.trade.settlement.bo.SettlementBillDataBO;
import com.tiancheng.trade.settlement.enums.*;
import com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.settlement.exception.error.CommonErrorInfoEnum;
import com.tiancheng.trade.settlement.feign.MerchantPaymentChannelService;
import com.tiancheng.trade.settlement.mapper.settlement.SettlementBillDataMapper;
import com.tiancheng.trade.settlement.mapper.settlement.SettlementWaitBillMapper;
import com.tiancheng.trade.settlement.model.settlement.SettlementBillData;
import com.tiancheng.trade.settlement.model.settlement.SettlementPayAcctConfig;
import com.tiancheng.trade.settlement.model.settlement.SettlementRule;
import com.tiancheng.trade.settlement.model.settlement.SettlementWaitBill;
import com.tiancheng.trade.settlement.service.settlement.ISettlementBillDataService;
import com.tiancheng.trade.settlement.service.settlement.ISettlementBillService;
import com.tiancheng.trade.settlement.service.settlement.ISettlementRuleService;
import com.tiancheng.trade.settlement.util.*;
import com.tiancheng.trade.settlement.vo.settlement.api.SettlementRuleVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class SettlementBillDataService implements ISettlementBillDataService {
    @Resource
    private PaymentFeignService paymentService;
    @Autowired
    private SettlementBillDataMapper settlementBillDataMapper;
    @Autowired
    private SettlementWaitBillMapper settlementWaitBillMapper;

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private ISettlementRuleService settlementRuleService;
    @Autowired
    private MerchantPaymentChannelService merchantPaymentChannelService;
    @Autowired
    private SettlementPayAcctConfigService settlementPayAcctConfigService;
    @Autowired
    private ISettlementBillService settlementBillService;

    /**
     * 计算应清分日期和应对账日期
     *
     * @return
     * @throws ParseException
     */
    private Map<String, Object> getShouldClearDateAndShouldBillDate(SettlementRule rule, LocalDateTime verifiedTime, LocalDateTime payTime) throws ParseException {
        Map<String, Object> dateMap = new HashMap<String, Object>();
        if (SettlementCycleModeEnum.DAY.getCode().equals(rule.getClearingCycleMode())) {//清分周期按天
            Date date = DateTimeUtil.LocalDateTimeToDate(verifiedTime);
            Calendar now = Calendar.getInstance();
            now.setTime(date);
            now.set(Calendar.DATE, now.get(Calendar.DATE) + rule.getClearingCycleValue());//+后 -前
            LocalDateTime shouldClearDate = DateTimeUtil.DateToLocalDateTime(now.getTime());//应清分日期
            LocalDateTime shouldBillDate = DateTimeUtil.getLocalDateTime(now.getTime(), 1);//应对账日期
            dateMap.put("shouldClearDate", shouldClearDate);
            dateMap.put("shouldBillDate", shouldBillDate);
        } else if (SettlementCycleModeEnum.MONTH.getCode().equals(rule.getClearingCycleMode())) {//清分周期按月
            int payTimeInt = DateTimeUtil.getYearMonth(DateTimeUtil.LocalDateTimeToDate(payTime));
            Date clearTime = DateTimeUtil.getNextMonthDay(DateTimeUtil.LocalDateTimeToDate(payTime), 1, rule.getClearingCycleValueExt());
            Date verifiedTimeDate = DateTimeUtil.LocalDateTimeToDate(verifiedTime);
            int verifiedTimeInt = DateTimeUtil.getYearMonth(DateTimeUtil.LocalDateTimeToDate(verifiedTime));
            if (payTimeInt == verifiedTimeInt) {//下单日期和核销日期在同一个月,则清分对账日期必然是下个月
                dateMap.put("shouldClearDate", DateTimeUtil.DateToLocalDateTime(clearTime));
                dateMap.put("shouldBillDate", DateTimeUtil.getLocalDateTime(clearTime, 1));

            } else {//下单日期和核销日期不在同一个月（下单日期只会小于核销日期）
                if (DateTimeUtil.JudgeDatesValue(verifiedTimeDate, clearTime) < 0) {//如果核销日期小于清出日期，则清分时间和对账时间在本月（本月对的是上月的账单）
                    dateMap.put("shouldClearDate", DateTimeUtil.DateToLocalDateTime(clearTime));
                    dateMap.put("shouldBillDate", DateTimeUtil.getLocalDateTime(clearTime, 1));
                } else {
                    //如果核销日期大于等于清出日期，则清分时间和对账时间在下月（下月对的是本月的账单）
                    Date clearTime2 = DateTimeUtil.getNextMonthDay(clearTime, 1, rule.getClearingCycleValueExt());
                    dateMap.put("shouldClearDate", DateTimeUtil.DateToLocalDateTime(clearTime2));
                    dateMap.put("shouldBillDate", DateTimeUtil.getLocalDateTime(clearTime2, 1));
                }
            }

        }
        return dateMap;
    }


    private boolean setSettlementBillData(SettlementRule rule, SettlementBillData data, MerchantPaymentChannelBO bo,
                                          Map<String, Object> amountMap) throws ParseException {
        if (rule != null) {
            data.setClearRuleCode(rule.getRuleCode());
            data.setClearingCycleMode(rule.getClearingCycleMode());
            data.setClearingCycleValue(rule.getClearingCycleValue());
            data.setClearingCycleValueExt(rule.getClearingCycleValueExt());
            data.setClearingRule(rule.getClearingRule());
            data.setRuleName(rule.getRuleName());
            data.setSettlementType(rule.getSettlementType());
            data.setCreatedDt(LocalDateTime.now());
            data.setVersion(0);
            LocalDateTime time = data.getVerifiedTime();
            if (Constant.DATA_TYPE_RE.equals(data.getTradeType())) {
                time = data.getRefundTime();
            }
            Map<String, Object> dateMap = getShouldClearDateAndShouldBillDate(rule, time, data.getPayTime());
            data.setShouldClearDate((LocalDateTime) dateMap.get("shouldClearDate"));
            data.setShouldBillDate((LocalDateTime) dateMap.get("shouldBillDate"));
            data.setIsException(false);
            data.setExceptionType(ExceptionTypeEnum.NORMAL.getCode());
            data.setProductCount(data.getProductCount() == null ? 1 : data.getProductCount());
            Integer subOrderAmount = data.getSubOrderAmount() / data.getProductCount();
            Double price = Double.parseDouble(String.valueOf(subOrderAmount)) / 100;
            //当订单金额不等于商品单价时，该核销单为异常单,通用规则不需要设置商品单价
            if (CommonUtil.RULE_PRODUCT_TYPE.equals(rule.getRuleType()) &&
                    !price.toString().equals(rule.getProductPrice())) {
                data.setIsException(true);
                data.setExceptionType(ExceptionTypeEnum.AMOUNT.getCode());
            }/*else if (DateTimeUtil.JudgeDatesValue(DateTimeUtil.LocalDateTimeToDate(data.getShouldBillDate()), new Date()) < 0) {
                 data.setIsException(true);
                 data.setExceptionType(ExceptionTypeEnum.RULE.getCode());
             }*/
        }
        if (null != bo) {
            data.setRate(bo.getPlatformSlottingFees());
            data.setSubMchId(bo.getSubMchId());
            if (Constant.DATA_TYPE_VE.equals(data.getTradeType())) {
                data.setServiceCharge(AmountUtil.getServiceCharge(data.getVerifiedAmount(), bo.getPlatformSlottingFees(), TransactionTypeEnum.PAY.getCode()));
            }
            //获取到商户中心的商户编码，保存到SettlementBillData表中
            if (StringUtils.isNotBlank(bo.getMerchantCode())) {
                data.setMerchantCode(bo.getMerchantCode());
            }
        }

        if (rule == null || bo == null) {
            data.setIsException(true);//异常
            data.setExceptionType(ExceptionTypeEnum.RULE.getCode());
            data.setDataStatus(Constant.DATA_STATUS_NS);
            return false;
        }
        return true;
    }


    private MerchantPaymentChannelBO getMerchantPaymentChannelBO(String merchantCode, String payChannelCode) {
        Result<MerchantPaymentChannelBO> res = merchantPaymentChannelService.findSubAppid(merchantCode, payChannelCode);
        return res.getData();
    }
    
    
   /* private void billDataAmountCalculation(SettlementBillData data,SettlementBillData model) {
    	if(Constant.DATA_TYPE_VE.equals(data.getTradeType())) {
    		model.setPayTime(data.getPayTime());
    		model.setFlowId(data.getFlowId());
    		model.setVerificationId(data.getVerificationId());
    		model.setVerifiedAmount(data.getVerifiedAmount());
    		model.setVerifiedTime(data.getVerifiedTime());
    		model.setDiscountAmount(data.getDiscountAmount());
    		model.setOrderId(data.getOrderId());
    		model.setSubOrderId(data.getSubOrderId());
    		model.setSubOrderAmount(data.getSubOrderAmount());
    		model.setSubOrderCount(data.getSubOrderCount());
    		model.setActualAmount(data.getActualAmount());
    		model.setCostPrice(data.getCostPrice());
    		model.setMerchantCode(data.getMerchantCode());
    		model.setMerchantName(data.getMerchantName());
    		model.setProductCode(data.getProductCode());
    		model.setProductCodeBusiness(data.getProductCodeBusiness());
    		model.setProductName(data.getProductName());
    		model.setProductCount(data.getProductCount());
    		model.setPayChannelCode(data.getPayChannelCode());
    		model.setOrderSource(data.getOrderSource());
    		model.setSubMchId(data.getSubMchId());
    		model.setRemark(data.getRemark());
        }else {
        	model.setRefundId(data.getRefundId());
        	model.setApplyRefundAmount(applyRefundAmount);
        	model.setRefundAmount(refundAmount);
        	model.setRefundTime(data.getRefundTime());
        }
    }*/

    /**
     * 保存账单，拆分账单数据到待对账
     *
     * @throws ParseException
     * @throws JsonProcessingException
     */
    @Override
    public int saveBill(List<SettlementBillDataBO> orderBO) throws Exception {
        //未核销发起退款，核销和退款的数据是多条一起给过来，已核销再退款，是分多次给
        if (orderBO == null || orderBO.isEmpty()) {
            return 0;
        }
        log.info("进入清分对账saveBill方法.... {}", orderBO.get(0).getSubOrderId());
        //由于订单中心只存了业务侧商品编号，所以这里要转成商户中心自己的商品编号
        List<String> productCodes = new ArrayList<>();
        productCodes.add(orderBO.get(0).getProductCode());
        String productCodeStr = String.join(",", productCodes);
        Result<List<ProductBO>> productBOList = merchantPaymentChannelService.getProductByBussessProductCode(productCodeStr);
        List<ProductBO> productList = null;
        if (productBOList.getRet() == 0) {
            productList = productBOList.getData();
        }
        log.info("查询商品信息是否为空.... {}", productList);
        if (productList != null && !productList.isEmpty()) {
            for (SettlementBillDataBO bo : orderBO) {
                bo.setProductCode(productList.get(0).getProductCode());
                bo.setProductCodeBusiness(productList.get(0).getProductCodeBusiness());
            }
        }
        SettlementRuleVO settlementRuleVO = new SettlementRuleVO();
        settlementRuleVO.setProductCode(orderBO.get(0).getProductCode());
        settlementRuleVO.setCurrentTime(DateTimeUtil.LocalDateTimeToDate(orderBO.get(0).getPayTime()));
        //获取当前产品的清分规则
        SettlementRule rule = settlementRuleService.getSettlementByCodeLevel(settlementRuleVO);
        log.info("查询清分规则是否为空.... {}", rule);
        //獲取商戶編碼以及通道費信息
        MerchantPaymentChannelBO merchantPaymentChannelBO = getMerchantPaymentChannelBO(orderBO.get(0).getMerchantCode(), orderBO.get(0).getPayChannelCode());
        int count = 0;
        for (SettlementBillDataBO bo : orderBO) {
            //待对账账单集合
            List<SettlementWaitBill> waitBills = new ArrayList<SettlementWaitBill>();
            log.info("核销数据{}", bo.getSubOrderId());
            SettlementBillData data = ObjectConvertUtil.convert(bo, SettlementBillData.class).get();
            //如果为退款做特殊处理
            if (null != data && null != data.getRefundAmount() && "RE".equals(data.getTradeType())) {
                data.setRefundAmount(0 - data.getRefundAmount());
            }
            int number = checkDataRepeat(data);
            if (number > 0) {
                log.info("子订单数据已经存在{}", data.getSubOrderId() + "," + data.getTradeType());
                return 0;
            }
            splitBillData(data, rule, merchantPaymentChannelBO, waitBills);
            log.info("单条对账单数据saveVerificationBasic {}", objectMapper.writeValueAsString(data));
            count = settlementBillDataMapper.insert(data);
            log.info("单条对账单数据是否保存成功 {}", count);
            if (count == 0) {
                return 0;
            }
            if (waitBills != null && waitBills.size() > 0) {
                log.info("保存待对账数据saveVerificationBasic {}", objectMapper.writeValueAsString(waitBills));
                int waitBillCount = settlementWaitBillMapper.saveBatch(waitBills);
                log.info("是否保存成功..... {}", waitBillCount);
                data.setDataStatus(Constant.DATA_STATUS_AS);
            }

        }
        return count;
    }

    /**
     * 校验数据是否已经存在
     *
     * @return
     */
    private int checkDataRepeat(SettlementBillData data) {
        QueryWrapper<SettlementBillData> conditions = new QueryWrapper<>();
        conditions.eq("sub_order_id", data.getSubOrderId());
        conditions.eq("flow_id", data.getFlowId());
        conditions.eq("trade_type", data.getTradeType());
        List<SettlementBillData> list = settlementBillDataMapper.selectList(conditions);
        if (null == list || list.isEmpty()) {
            return 0;
        }
        return list.size();
    }

    /**
     * 拆分账单数据
     *
     * @param data
     * @param rule
     * @param merchantPaymentChannelBO
     * @param waitBills
     * @throws ParseException
     */
    public void splitBillData(SettlementBillData data, SettlementRule rule,
                              MerchantPaymentChannelBO merchantPaymentChannelBO,
                              List<SettlementWaitBill> waitBills) throws ParseException {
        Map<String, Object> amountMap = new HashMap<String, Object>();
        boolean bool = setSettlementBillData(rule, data, merchantPaymentChannelBO, amountMap);
        if (bool) {
            getServiceChargeAndMarketingExpenses(amountMap, rule, data,
                    merchantPaymentChannelBO.getMerchantSlottingFees(),
                    merchantPaymentChannelBO.getPlatformSlottingFees());
            Integer bondSlottingFees = (Integer) amountMap.get("bondSlottingFees");
            Integer merchantDeserved = (Integer) amountMap.get("merchantDeserved");
            Integer platformDeserved = (Integer) amountMap.get("platformDeserved");
            Integer discountAmount = (Integer) amountMap.get("discountAmount");
            String subMchId = merchantPaymentChannelBO.getSubMchId();
            if (null != merchantDeserved && merchantDeserved != 0) {//生成商户应得
                SettlementWaitBill waitBill = setSettlementWaitBillParams(data, merchantDeserved, subMchId, CostTypeEnum.ME.getCode());
                waitBills.add(waitBill);
            }
            if (null != platformDeserved && platformDeserved != 0) {//生成平台应得
                SettlementWaitBill waitBill = setSettlementWaitBillParams(data, platformDeserved, subMchId, CostTypeEnum.PL.getCode());
                waitBills.add(waitBill);
            }
            if (null != discountAmount && discountAmount != 0) {//生成营销费用
                SettlementWaitBill waitBill = setSettlementWaitBillParams(data, discountAmount, subMchId, CostTypeEnum.CU.getCode());
                waitBills.add(waitBill);
            }
            if (null != bondSlottingFees && bondSlottingFees != 0) {//生成通道费
                SettlementWaitBill waitBill = setSettlementWaitBillParams(data, bondSlottingFees, subMchId, CostTypeEnum.SC.getCode());
                waitBills.add(waitBill);
            }
            if (!waitBills.isEmpty()) {
                data.setDataStatus(Constant.DATA_STATUS_AS);
            }
        } else {//当清分规则未配置的时候，待对账表也保存一条异常数据，方便页面的查询
            SettlementWaitBill waitBill = setSettlementWaitBillParams(data, 0, null, null);
            waitBills.add(waitBill);
        }
    }

    /**
     * 设置待对账信息
     *
     * @param data
     * @param deserved
     * @param subMchId
     * @param costType
     * @return
     */
    private SettlementWaitBill setSettlementWaitBillParams(SettlementBillData data, Integer deserved, String subMchId, String costType) {
        SettlementWaitBill waitBill = new SettlementWaitBill();
        //如果是退款做特殊处理
        if ("RE".equals(data.getTradeType())) {
            waitBill.setClearAmount(0 - deserved);
        } else {
            waitBill.setClearAmount(deserved);
        }

        waitBill.setMerchantCode(data.getMerchantCode());
        waitBill.setSubMchId(subMchId);
        waitBill.setOrderId(data.getOrderId());
        waitBill.setSubOrderId(data.getSubOrderId());
        waitBill.setBillStatus(BillStatusEnum.WAIT.getCode());
        waitBill.setCostType(costType);
        waitBill.setTradeType(data.getTradeType());
        waitBill.setBasePublicParam(LocalDateTime.now(), "system", LocalDateTime.now(), "system", 0);
        waitBill.setShouldBillDate(data.getShouldBillDate());
        waitBill.setExceptionType(data.getExceptionType());
        SettlementPayAcctConfig param = new SettlementPayAcctConfig();
        param.setPayChannel(data.getPayChannelCode());
        param.setCostType(costType);
        List<SettlementPayAcctConfig> list = settlementPayAcctConfigService.queryList(param);
        if (null != list && !list.isEmpty()) {
            SettlementPayAcctConfig config = list.get(0);
            waitBill.setPayAcct(config.getPayAcct());
            waitBill.setPayAcctName(config.getPayAcctName());
            if (CostTypeEnum.ME.getCode().equals(costType)) {
                Result<MerchantBO> res = merchantPaymentChannelService.findMerchant(data.getMerchantCode());
                MerchantBO merchantBO = null;
                if (res != null && 0 == res.getRet()) {
                    merchantBO = res.getData();
                }
                if (null != merchantBO) {
                    waitBill.setColAcct(merchantBO.getAccountNo());
                    waitBill.setColAcctName(merchantBO.getAccountName());
                }
            } else {
                waitBill.setColAcct(config.getColAcct());
                waitBill.setColAcctName(config.getColAcctName());
            }
        }
        return waitBill;
    }


    public Map<String, Object> getCostTypeMap(String payChannel) {
        Map<String, Object> map = new HashMap<String, Object>();
        SettlementPayAcctConfig param = new SettlementPayAcctConfig();
        param.setPayChannel(payChannel);
        List<SettlementPayAcctConfig> list = settlementPayAcctConfigService.queryList(param);
        if (null != list && list.size() > 0) {
            for (SettlementPayAcctConfig config : list) {
                String colAcct = config.getColAcct() == null ? "" : config.getColAcct();
                map.put(config.getPayAcct() + "|" + colAcct, config.getCostType());
            }
        }
        return map;
    }


    public String getCostType(Map<String, Object> map, String payAcct, String colAcct) {
        if (map.get(payAcct + "|" + colAcct) == null) {
            if (map.get(payAcct + "|") != null) {//收款方账户在对账中心配置为空，因为清分给商户时每个商户号不一样
                return CostTypeEnum.ME.getCode();
            } else {
                return "";
            }
        }
        return map.get(payAcct + "|" + colAcct).toString();
    }

    private void getServiceChargeAndMarketingExpenses(Map<String, Object> amountMap, SettlementRule rule, SettlementBillData data, BigDecimal merchantSlottingFees, BigDecimal platformSlottingFees) {
        Integer serviceCharge = 0;//手续费
        Integer merchantShould = 0;//商户应得
        Integer platformShould = 0;//平台应得
        Integer discountAmount = 0; //优惠金额
        Integer bondSlottingFees = 0;//保证金账户需要出的钱
        Integer verifiedAmount = 0; //核销金额（退款时为退款金额）
        try {
            if (Constant.DATA_TYPE_VE.equals(data.getTradeType())) {
                verifiedAmount = data.getVerifiedAmount(); //核销金额
            } else {
                verifiedAmount = Math.abs(data.getRefundAmount()); //退款金额
            }
            //计算出手续费
            serviceCharge = AmountUtil.getServiceCharge(verifiedAmount, platformSlottingFees, TransactionTypeEnum.PAY.getCode());
            merchantShould = getMerchantShould(verifiedAmount, rule.getClearingRule(), rule);
            platformShould = (verifiedAmount - merchantShould);
            discountAmount = data.getDiscountAmount();
        } catch (Exception e) {
            log.info("getServiceChargeAndMarketingExpenses方法出现异常 {}", e.getMessage());
        }
        if (platformShould < Math.abs(serviceCharge)) {
            //如果清分给平台的钱比手续费少，则需要从保证金账户出钱给到待清算资金专户，清分给平台的钱为0
            // bondSlottingFees = platformShould - Math.abs(serviceCharge);
            platformShould = 0;
        }
        amountMap.put("bondSlottingFees", bondSlottingFees);//保证金账户需要出的手续费
        amountMap.put("merchantDeserved", merchantShould);//清分给商户
        amountMap.put("platformDeserved", platformShould);//清分给平台
        amountMap.put("discountAmount", discountAmount);//优惠总金额
    }

    private static Integer getMerchantShould(Integer amount, String tradeType, SettlementRule rule) {
        if (SettlementClearRuleEnum.PERCENTAGE.getCode().equals(rule.getClearingRule())) {
            BigDecimal oneHundred = new BigDecimal(100);
            //商户应得百分比
            BigDecimal merchantReceivable = rule.getMerchantPre().divide(oneHundred, 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal amountBig = BigDecimal.valueOf(amount).divide(oneHundred, 2, BigDecimal.ROUND_HALF_UP);
            double resDouble = amountBig.multiply(merchantReceivable).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            BigDecimal resStr = BigDecimal.valueOf(resDouble);
            Integer merchantShould = resStr.multiply(new BigDecimal(100)).intValue();
            return merchantShould;
        } else {
            //按固定金额清分
            return (amount - rule.getMerchantFix());
        }
    }

    @Override
    public Result matchingRule(List<String> subOrderIds, SettlementRule rule) {
        try {
            List<SettlementWaitBill> allData = getAllData(subOrderIds, rule, "");
            if (allData == null || allData.isEmpty()) {
                return Result.fail(BusinessErrorInfoEnum.SETTLEMENT_RULE_ERROR.getCode(), BusinessErrorInfoEnum.SETTLEMENT_RULE_ERROR.getMessage());
            }
            List<String> subOrderKeys = new ArrayList<String>();
            List<String> waits = new ArrayList<String>();
            //用本次匹配的子订单号与费用类型，去银行详情表对账
            for (SettlementWaitBill bill : allData) {
                subOrderKeys.add(bill.getSubOrderId() + bill.getCostType() + bill.getTradeType());
                waits.add(bill.getSubOrderId() + bill.getTradeType());
            }
            settlementWaitBillMapper.deleteRematchData(subOrderKeys);
            //如果当前子订单下的账单多次匹配清分规则并且还没有对账，则删除上一次生成的待对账数据，用最新的等待对账
            settlementWaitBillMapper.deleteWaitBill(waits);
            settlementWaitBillMapper.saveBatch(allData);
            //目前重新匹配清分规则后的数据全都立即处罚对账，不需要考虑应对账时间
            settlementBillService.matchingRuleReconciliation(subOrderKeys, rule);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(CommonErrorInfoEnum.SYSTEM_ERROR.getCode(), CommonErrorInfoEnum.SYSTEM_ERROR.getMessage());
        }
        return Result.success();
    }

    private List<SettlementWaitBill> getAllData(List<String> subOrderIds, SettlementRule rule, String flag) {
        int count = settlementBillDataMapper.updateBillClearRule(subOrderIds, rule);
        if (count > 0) {
            List<SettlementBillData> datas = settlementBillDataMapper.selectBillDataBySubOrderIds(subOrderIds);
            List<String> errorData = new ArrayList<String>();
            List<SettlementWaitBill> waitBills = new ArrayList<SettlementWaitBill>();
            for (SettlementBillData data : datas) {//循环拆分每条子订单数据
                MerchantPaymentChannelBO bo = new MerchantPaymentChannelBO();
                if (StringUtils.isEmpty(data.getSubMchId())) {
                    MerchantPaymentChannelBO merchantPaymentChannelBO = getMerchantPaymentChannelBO(data.getMerchantCode(), data.getPayChannelCode());
                    bo.setPlatformSlottingFees(merchantPaymentChannelBO.getPlatformSlottingFees());//目前的手续费率都是来自平台
                    bo.setSubMchId(merchantPaymentChannelBO.getSubMchId());
                } else {
                    bo.setPlatformSlottingFees(data.getRate());//目前的手续费率都是来自平台
                    bo.setSubMchId(data.getSubMchId());
                }
                try {
                    splitBillData(data, rule, bo, waitBills);
                } catch (ParseException e) {
                    errorData.add(data.getSubOrderId());
                    e.printStackTrace();
                    break;
                }
                //更新账单信息
                settlementBillDataMapper.updateBillDataInfo(data);
            }
            return waitBills;
        }
        return null;

    }


    @Override
    public Result waitBillMatchingRule(List<String> subOrderIds, SettlementRule rule) {
        List<SettlementWaitBill> allData = getAllData(subOrderIds, rule, "wait");
        if (allData == null || allData.isEmpty()) {
            return Result.fail(BusinessErrorInfoEnum.SETTLEMENT_RULE_ERROR.getCode(), BusinessErrorInfoEnum.SETTLEMENT_RULE_ERROR.getMessage());
        }
        List<String> subOrderKeys = new ArrayList<String>();
        //用本次匹配的子订单号与费用类型，去银行详情表对账
        for (SettlementWaitBill bill : allData) {
            subOrderKeys.add(bill.getSubOrderId() + bill.getTradeType());
        }
        //如果当前子订单下的账单多次匹配清分规则并且还没有对账，则删除上一次生成的待对账数据，用最新的等待对账
        settlementWaitBillMapper.deleteWaitBill(subOrderKeys);
        //保存本次拆分
        settlementWaitBillMapper.saveBatch(allData);
        return Result.success("处理成功");
    }

}
